home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Developer Kit / QuickTime 2.0 Developer Kit.iso / mac / MAC / Programming Stuff / Documentation / develop / develop Issue 12 / develop 12 code / Components / ComponentTester.c < prev    next >
Encoding:
Text File  |  1992-10-16  |  38.7 KB  |  1,678 lines  |  [TEXT/KAHL]

  1. /*
  2.     File:        ComponentTester.c
  3.  
  4.     Contains:    Component tester routines.
  5.  
  6.     Written by:    Gary Woodcock
  7.  
  8.     Copyright:    © 1992 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12. */
  13.  
  14. //-----------------------------------------------------------------------
  15. // Includes
  16.  
  17. #include "MathComponent.h"
  18. #include "MathComponentPrivate.h"
  19. #include "MoMathComponent.h"
  20. #include "MoMathComponentPrivate.h"
  21. #include "NuMathComponentPrivate.h"
  22. #include <Menus.h>
  23. #include <Windows.h>
  24. #include <QuickDraw.h>
  25. #include <OSEvents.h>
  26. #include <Resources.h>
  27. #include <Desk.h>
  28. #include <Fonts.h>
  29. #include <ToolUtils.h>
  30.  
  31. #ifndef THINK_C
  32.     #include <Packages.h>
  33. #endif THINK_C
  34.  
  35. // Make sure the debug flag in this file is set appropriately
  36. #include "DebugFlags.h"    
  37.  
  38. //-----------------------------------------------------------------------
  39. // Constants
  40.  
  41. // Maximum number of instances our app can open
  42. #define    kMaxInstances    10
  43.  
  44. // Menu bar
  45. enum
  46. {
  47.     kMenuBarID = 128
  48. };
  49.  
  50. // Menus
  51. enum
  52. {
  53.     kAppleID = 128,
  54.     kFileID,
  55.     kEditID,
  56.     kTestID,
  57.     kCanDoID,
  58.     kInstanceID
  59. };
  60.  
  61. // Apple menu items
  62. enum
  63. {
  64.     kAboutItem = 1
  65. };
  66.  
  67. // File menu items
  68. enum
  69. {
  70.     kOpenItem = 1,
  71.     kCloseItem,
  72.     
  73.     #ifdef DEBUG_IT
  74.         kOpenMathComponentItem = 4,
  75.         kOpenMoMathComponentItem,
  76.         kOpenNuMathComponentItem,
  77.         kCloseComponentItem,
  78.         kQuitItem = 9
  79.     #else
  80.         kOpenMoMathComponentItem = 4,
  81.         kOpenNuMathComponentItem,
  82.         kCloseComponentItem,
  83.         kQuitItem = 8
  84.     #endif DEBUG_IT
  85. };
  86.  
  87. // Edit menu items
  88. enum
  89. {
  90.     kUndoItem = 1,
  91.     kCutItem = 3,
  92.     kCopyItem,
  93.     kPasteItem,
  94.     kClearItem
  95. };
  96.  
  97. // Test menu items
  98. enum
  99. {
  100.     kGetNameItem = 1,
  101.     kGetInfoItem,
  102.     kGetVersionItem,
  103.     kGetCountItem,
  104.     kGetRefconItem,
  105.     kGetA5Item,
  106.     kCanDoItem = 8,
  107.     kDoDivideItem = 10,
  108.     kDoMultiplyItem,
  109.     kDoAddItem
  110. };
  111.  
  112. // Can Do hierarchical menu items
  113. enum
  114. {
  115.     kCanDoOpenItem = 1,
  116.     kCanDoCloseItem,
  117.     kCanDoCanDoItem,
  118.     kCanDoVersionItem,
  119.     kCanDoRegisterItem,
  120.     kCanDoTargetItem,
  121.     kCanDoDoDivideItem = 8,
  122.     kCanDoDoMultiplyItem,
  123.     kCanDoDoAddItem
  124. };
  125.  
  126. // Registration flags
  127. enum
  128. {
  129.     kRegisterLocally = 0,
  130.     kRegisterGlobally
  131. };
  132.  
  133. // Dialog IDs
  134. enum
  135. {
  136.     kAboutDialogID = 128,
  137.     kStatusDialogID,
  138.     kOpDialogID
  139. };
  140.  
  141. // Common DITL items
  142. enum
  143. {
  144.     kOKButton = 1,
  145.     kCancelButton,
  146.     kOKButtonOutline
  147. };
  148.  
  149. // DITL items for operations dialog
  150. enum
  151. {
  152.     kFirstNumBox = 4,
  153.     kSecondNumBox
  154. };
  155.  
  156. // DITL items for status dialog
  157. enum
  158. {
  159.     kStatusBox = 1
  160. };
  161.  
  162. // String list
  163. enum
  164. {
  165.     kStatusStrsID = 128
  166. };
  167.  
  168. // Strings
  169. enum
  170. {
  171.     kIdleStr = 1,
  172.     kFoundCompIDAndInstStr,
  173.     kDidNotFindCompIDStr,
  174.     kDidNotGetInstStr,
  175.     kClosedOKStr,
  176.     kErrorClosingInstStr,
  177.     kCompVersStr,
  178.     kInterfaceVersStr,
  179.     kCanDoOpenStr,
  180.     kCantDoOpenStr,
  181.     kCanDoCloseStr,
  182.     kCantDoCloseStr,
  183.     kCanDoCanDoStr,
  184.     kCantDoCanDoStr,
  185.     kCanDoVersionStr,
  186.     kCantDoVersionStr,
  187.     kCanDoRegisterStr,
  188.     kCantDoRegisterStr,
  189.     kCanDoTargetStr,
  190.     kCantDoTargetStr,
  191.     kNameStr,
  192.     kNoNameStr,
  193.     kInfoStr,
  194.     kNoInfoStr,
  195.     kRefconStr,
  196.     kThereIsStr,
  197.     kThereAreStr,
  198.     kInstanceStr,
  199.     kInstancesStr,
  200.     kA5Str,
  201.     kDivideResultStr,
  202.     kCanDoDoDivideStr,
  203.     kCantDoDoDivideStr,
  204.     kMultiplyResultStr,
  205.     kCanDoDoMultiplyStr,
  206.     kCantDoDoMultiplyStr,
  207.     kAddResultStr,
  208.     kCanDoDoAddStr,
  209.     kCantDoDoAddStr,
  210.     kCantOpenAnyMoreInstStr,
  211.     kCompDescStr,
  212.     kMathStr,
  213.     kMoMathStr,
  214.     kNuMathStr,
  215.     kKeyPhrase
  216. };
  217.  
  218. // Math component variants
  219. typedef    enum    MathType
  220. {
  221.     kMathComponent = 1,
  222.     kMoMathComponent,
  223.     kNuMathComponent
  224. }
  225. MathType;
  226.  
  227. //-----------------------------------------------------------------------
  228. // Globals
  229.  
  230. MenuHandle            gAppleMenu;
  231. MenuHandle            gFileMenu;
  232. MenuHandle            gEditMenu;
  233. MenuHandle            gTestMenu;
  234. MenuHandle            gCanDoMenu;
  235. MenuHandle            gInstanceMenu;
  236. EventRecord            gTheEvent;
  237. Component            gMathComponentID;
  238. Component            gMoMathComponentID;
  239. Component            gNuMathComponentID;
  240. ComponentInstance    gComponentInstance [kMaxInstances];
  241. ComponentInstance    gCurrentInstance;
  242. DialogPtr            gStatusDialog;
  243. GrafPtr                gSavedPort;
  244. Str255                gStatusStr;
  245. Rect                gStatusBox;
  246. Handle                gStatusText;
  247. Handle                gMathNameHdl;
  248. Handle                gMoMathNameHdl;
  249. Handle                gNuMathNameHdl;
  250. Handle                gInfoHdl;
  251. Str255                gKeyPhrase;
  252. Boolean                gQuitFlag;
  253.  
  254. //-----------------------------------------------------------------------
  255. // Prototypes
  256.  
  257. void                DoInit                    (void);
  258. void                DoMenuSetup                (void);
  259. void                HandleEvent                (void);
  260. void                HandleMouseDown            (void);
  261. void                AdjustMenus                (void);
  262. void                Enable                    (Handle        menu,
  263.                                              short        item,
  264.                                              Boolean    ok);
  265. void                HandleMenu                (long        menu);
  266. void                OpenStatus                (void);
  267. void                UpdateStatus            (void);
  268. void                DoAboutDialog            (void);
  269. void                OpenMathComponent        (MathType    whichOne);
  270. void                DoOperationDialog        (short        *numerator,
  271.                                              short        *denominator);
  272. static pascal void    DrawOKOutline            (DialogPtr    theDialog,
  273.                                              short        theItem);
  274. void                DoQuit                    (void);
  275. void                DecimalNumberToHexStr    (long        theDecimalNumber,
  276.                                              StringPtr    theHexStr);
  277. OSErr                HexStrToDecimalNumber    (StringPtr    theHexStr,
  278.                                              long        *theDecimalNumber);
  279.  
  280. //-----------------------------------------------------------------------
  281.  
  282. main    (void)
  283. {
  284.     // Init
  285.     DoInit();
  286.     DoMenuSetup();
  287.     OpenStatus();
  288.     
  289.     // Eat events until done
  290.     do
  291.     {
  292.         HandleEvent();
  293.     }
  294.     while (!gQuitFlag);
  295.     
  296.     // Take off, eh?
  297.     ExitToShell();
  298. }
  299.  
  300. //-----------------------------------------------------------------------
  301.  
  302. void    DoInit    (void)
  303. {
  304.     short                    i;
  305.     ComponentDescription    mathDesc;
  306.     
  307.     // Set up quit flag
  308.     gQuitFlag = false;
  309.     
  310.     // MacMantra™
  311.     MaxApplZone();
  312.     InitGraf (&qd.thePort);
  313.     InitFonts();
  314.     FlushEvents (everyEvent, 0);
  315.     InitWindows();
  316.     InitMenus();
  317.     TEInit();
  318.     InitDialogs (0L);
  319.     InitCursor();
  320.     MoreMasters();
  321.     MoreMasters();
  322.     MoreMasters();
  323.     MoreMasters();
  324.     
  325.     // Get initial strings
  326.     GetIndString (gStatusStr, kStatusStrsID, kIdleStr);
  327.     GetIndString (gKeyPhrase, kStatusStrsID, kKeyPhrase);
  328.     
  329.     // Init instance stuff
  330.     gMathComponentID = 0L;
  331.     gMoMathComponentID = 0L;
  332.     gNuMathComponentID = 0L;
  333.     gCurrentInstance = 0L;
  334.     for (i = 0; i < kMaxInstances; i++)
  335.         gComponentInstance[i] = 0L;
  336.         
  337.     // Register (or find) our components
  338.     mathDesc.componentType = mathComponentType;
  339.     mathDesc.componentSubType = 0L;
  340.     mathDesc.componentManufacturer = 'appl';
  341.     mathDesc.componentFlags = 0L;
  342.     mathDesc.componentFlagsMask = 0L;
  343.     
  344.     // Are we debugging?
  345.     #ifdef DEBUG_IT
  346.     
  347.         if (gMathNameHdl == nil)
  348.         {
  349.             Str255    mathName = "\pMath Component";
  350.             
  351.             gMathNameHdl = NewHandle (sizeof (Str255));
  352.             BlockMove ((Ptr)&mathName, (Ptr)(*gMathNameHdl), mathName[0] + 1);
  353.         }
  354.         if (gMoMathNameHdl == nil)
  355.         {
  356.             Str255    moMathName = "\pMoMath Component";
  357.             
  358.             gMoMathNameHdl = NewHandle (sizeof (Str255));
  359.             BlockMove ((Ptr)&moMathName, (Ptr)(*gMoMathNameHdl), moMathName[0] + 1);
  360.         }
  361.         if (gNuMathNameHdl == nil)
  362.         {
  363.             Str255    nuMathName = "\pNuMath Component";
  364.             
  365.             gNuMathNameHdl = NewHandle (sizeof (Str255));
  366.             BlockMove ((Ptr)&nuMathName, (Ptr)(*gNuMathNameHdl), nuMathName[0] + 1);
  367.         }
  368.         if (gInfoHdl == nil)
  369.         {
  370.             Str255    mathInfo = "\pThis component provides simple math services.";
  371.             
  372.             gInfoHdl = NewHandle (sizeof (Str255));
  373.             BlockMove ((Ptr)&mathInfo, (Ptr)(*gInfoHdl), mathInfo[0] + 1);
  374.         }
  375.         
  376.         // Register the Math component
  377.         gMathComponentID = RegisterComponent (&mathDesc,
  378.             (ComponentRoutine) MathDispatcher, kRegisterLocally,
  379.             gMathNameHdl, gInfoHdl, nil);
  380.             
  381.         // Register the NuMath component
  382.         mathDesc.componentFlags = 0x80000000;
  383.         gNuMathComponentID = RegisterComponent (&mathDesc,
  384.             (ComponentRoutine) NuMathDispatcher, kRegisterLocally,
  385.             gNuMathNameHdl, gInfoHdl, nil);
  386.             
  387.         // Register the MoMath component
  388.         mathDesc.componentManufacturer = moMathComponentMfg;
  389.         mathDesc.componentFlags = 0L;
  390.         gMoMathComponentID = RegisterComponent (&mathDesc,
  391.             (ComponentRoutine) MoMathDispatcher, kRegisterLocally,
  392.             gMoMathNameHdl, gInfoHdl, nil);
  393.         
  394.     #else    // We're running as standalone components    
  395.     
  396.         // Find the NuMath component - Note that we won't be able to find the
  397.         // Math component, because the NuMath component captured it.  In essence,
  398.         // the NuMath component completely replaces the Math component (from an
  399.         // application point of view).    Also, you should note that it is perfectly
  400.         // acceptable to do a RegisterComponent call followed by a FindNextComponent
  401.         // call - if you use the same component description, and the
  402.         // RegisterComponent call was successful, then you'll get back the same
  403.         // component ID from FindNextComponent that you got from RegisterComponent.    
  404.         gNuMathComponentID = FindNextComponent (nil, &mathDesc);
  405.         
  406.         // Find the MoMath component
  407.         mathDesc.componentManufacturer = moMathComponentMfg;
  408.         gMoMathComponentID = FindNextComponent (nil, &mathDesc);    
  409.                 
  410.     #endif DEBUG_IT    
  411. }
  412.  
  413. //-----------------------------------------------------------------------
  414.  
  415. void    DoMenuSetup    (void)
  416. {    
  417.     Handle    theMenuBar = GetNewMBar (kMenuBarID);
  418.     
  419.     // Set up our menus
  420.     SetMenuBar (theMenuBar);
  421.     gAppleMenu = GetMHandle (kAppleID);
  422.     gFileMenu = GetMHandle (kFileID);
  423.     
  424.     // We don't need the "Open Math Component" item unless
  425.     // we're debugging
  426.     #ifndef DEBUG_IT
  427.         DelMenuItem (gFileMenu, 4);
  428.     #endif DEBUG_IT
  429.     
  430.     gEditMenu = GetMHandle (kEditID);
  431.     gTestMenu = GetMHandle (kTestID);
  432.     gInstanceMenu = GetMHandle (kInstanceID);
  433.     gCanDoMenu = GetMenu (kCanDoID);
  434.     InsertMenu (gCanDoMenu, hierMenu);
  435.     AddResMenu (gAppleMenu, 'DRVR');
  436.     DrawMenuBar();
  437. }
  438.  
  439. //-----------------------------------------------------------------------
  440.  
  441. void    HandleEvent    (void)
  442. {
  443.     Boolean    ok = false;
  444.  
  445.     // Do system stuff
  446.     HiliteMenu (0);
  447.     SystemTask();
  448.     
  449.     // Suck an event
  450.     ok = WaitNextEvent (everyEvent, &gTheEvent, 0, 0);
  451.     if (ok)
  452.     {
  453.         // What was it?
  454.         switch (gTheEvent.what)
  455.         {
  456.             case mouseDown:
  457.             {
  458.                 HandleMouseDown();
  459.                 break;
  460.             }
  461.             case keyDown:
  462.             case autoKey:
  463.             {
  464.                 char    theChar = gTheEvent.message & charCodeMask;
  465.                 long    theMenu = MenuKey (theChar);
  466.  
  467.                 HandleMenu (theMenu);                
  468.                 break;
  469.             }
  470.             case updateEvt:
  471.             {
  472.                 if (IsDialogEvent (&gTheEvent))
  473.                 {
  474.                     // Update the status dialog
  475.                     GetPort (&gSavedPort);
  476.                     SetPort (gStatusDialog);
  477.                     BeginUpdate (gStatusDialog);
  478.                     InsetRect (&gStatusBox, -2, -2);
  479.                     FrameRect (&gStatusBox);
  480.                     InsetRect (&gStatusBox, 2, 2);
  481.                     EraseRect (&gStatusBox);
  482.                     SetIText (gStatusText, gStatusStr);
  483.                     EndUpdate (gStatusDialog);
  484.                     SetPort (gSavedPort);
  485.                 }
  486.             }
  487.             default:    // We don't really care about any other events
  488.             {
  489.                 break;
  490.             }
  491.         }
  492.     }
  493. }
  494.  
  495. //-----------------------------------------------------------------------
  496.  
  497. void    HandleMouseDown    (void)
  498. {    
  499.     WindowPtr    theWindow;
  500.     short        windowCode = FindWindow (gTheEvent.where, &theWindow);
  501.     
  502.     // Where was the mouse down?
  503.     switch (windowCode)
  504.     {
  505.         case inSysWindow:
  506.         { 
  507.             SystemClick (&gTheEvent, theWindow);
  508.             break;
  509.         }
  510.         case inMenuBar:
  511.         {
  512.             AdjustMenus();
  513.             HandleMenu (0L);
  514.             break;
  515.         }
  516.         case inDrag:
  517.         {
  518.             DragWindow (theWindow, gTheEvent.where, &(qd.screenBits.bounds));
  519.             break;
  520.         }
  521.         case inGoAway:
  522.         {
  523.             if ((theWindow == gStatusDialog) && 
  524.                 TrackGoAway (gStatusDialog, gTheEvent.where))
  525.             {
  526.                 DisposDialog (gStatusDialog);
  527.                 gStatusDialog = nil;
  528.             }
  529.             break;
  530.         }
  531.         default:
  532.         {
  533.             break;
  534.         }
  535.     }
  536. }
  537.  
  538. //-----------------------------------------------------------------------
  539.  
  540. void    AdjustMenus    (void)
  541. {
  542.     register WindowPeek        wp = nil;
  543.     short                    kind = 0;
  544.     Boolean                    DA = false;
  545.     ComponentDescription    compDesc;
  546.     ComponentResult            result = noErr;
  547.     
  548.     // What kind of window is frontmost?
  549.     wp = (WindowPeek) FrontWindow();
  550.     kind = wp ? wp->windowKind : 0;
  551.     DA = kind < 0;
  552.     
  553.     // Set our menu item states appropriately
  554.     
  555.     // Apple menu
  556.     Enable ((Handle) gAppleMenu, kAboutItem, true);    
  557.     
  558.     // File menu
  559.     Enable ((Handle) gFileMenu, kOpenItem, (gStatusDialog == nil) ? true : false);
  560.     Enable ((Handle) gFileMenu, kCloseItem, DA || ((gStatusDialog != nil) ? true : false));
  561.     
  562.     #ifdef DEBUG_IT
  563.         Enable ((Handle) gFileMenu, kOpenMathComponentItem, true);
  564.     #endif DEBUG_IT
  565.     
  566.     Enable ((Handle) gFileMenu, kOpenMoMathComponentItem, true);
  567.     Enable ((Handle) gFileMenu, kOpenNuMathComponentItem, true);
  568.     Enable ((Handle) gFileMenu, kCloseComponentItem, (gCurrentInstance != 0L) ? true : false);
  569.     Enable ((Handle) gFileMenu, kQuitItem, true);
  570.  
  571.     // Edit menu
  572.     Enable ((Handle) gEditMenu, 1, DA);
  573.     Enable ((Handle) gEditMenu, 3, DA);
  574.     Enable ((Handle) gEditMenu, 4, DA);
  575.     Enable ((Handle) gEditMenu, 5, DA);
  576.     Enable ((Handle) gEditMenu, 6, DA);
  577.     
  578.     // Test menu
  579.     Enable ((Handle) gTestMenu, kCanDoItem, (gCurrentInstance != 0L) ? true : false);
  580.     Enable ((Handle) gTestMenu, kGetVersionItem, (gCurrentInstance != 0L) ? true : false);
  581.     Enable ((Handle) gTestMenu, kGetNameItem, (gCurrentInstance != 0L) ? true : false);
  582.     Enable ((Handle) gTestMenu, kGetInfoItem, (gCurrentInstance != 0L) ? true : false);
  583.     Enable ((Handle) gTestMenu, kGetRefconItem, (gCurrentInstance != 0L) ? true : false);
  584.     Enable ((Handle) gTestMenu, kGetCountItem, (gCurrentInstance != 0L) ? true : false);
  585.     Enable ((Handle) gTestMenu, kGetA5Item, (gCurrentInstance != 0L) ? true : false);
  586.     Enable ((Handle) gTestMenu, kDoDivideItem, (gCurrentInstance != 0L) ? true : false);
  587.     Enable ((Handle) gTestMenu, kDoMultiplyItem, (gCurrentInstance != 0L) ? true : false);
  588.  
  589.     // Only enable add stuff if a MoMath component is around
  590.     if (gCurrentInstance != 0L)
  591.     {
  592.         result = GetComponentInfo ((Component)(gCurrentInstance), &compDesc, nil, nil, nil);
  593.         if (compDesc.componentManufacturer == moMathComponentMfg)
  594.         {
  595.             Enable ((Handle) gTestMenu, kDoAddItem, true);
  596.         }
  597.         else
  598.         {
  599.             Enable ((Handle) gTestMenu, kDoAddItem, false);
  600.         }
  601.     }
  602.     else
  603.     {
  604.         Enable ((Handle) gTestMenu, kDoAddItem, false);
  605.     }
  606.     
  607.     // Figure out which item is checked in the Instance menu
  608.     if (CountMItems (gInstanceMenu) > 0)
  609.     {
  610.         short    i;
  611.         short    j;
  612.         long    tempInst;
  613.         Str255    menuItemStr;
  614.         Str255    tempInstStr;
  615.         
  616.         // Enable the menu
  617.         EnableItem (gInstanceMenu, 0);
  618.         
  619.         // Examine each item
  620.         for (i = 1; i <= CountMItems (gInstanceMenu); i++)
  621.         {
  622.             Boolean    foundKey = false;
  623.             
  624.             // Uncheck the item
  625.             CheckItem (gInstanceMenu, i, false);
  626.             
  627.             // Get the item string
  628.             GetItem (gInstanceMenu, i, menuItemStr);
  629.             
  630.             // Extract the instance number from the menu string
  631.             GetItem (gInstanceMenu, i, menuItemStr);
  632.             for (j = 1; j <= menuItemStr[0]; j++)
  633.             {
  634.                 if ((gKeyPhrase[1] == menuItemStr[j]) &&
  635.                     (gKeyPhrase[2] == menuItemStr[j + 1]) &&
  636.                     (gKeyPhrase[3] == menuItemStr[j + 2]) &&
  637.                     (gKeyPhrase[4] == menuItemStr[j + 3]) &&
  638.                     (gKeyPhrase[5] == menuItemStr[j + 4]))
  639.                 {
  640.                     foundKey = true;
  641.                     break;
  642.                 }
  643.             }
  644.             
  645.             // Did we find the phrase key?
  646.             if (foundKey)
  647.             {
  648.                 // Copy the instance string
  649.                 BlockMove ((Ptr)&menuItemStr[j + 5], (Ptr)&tempInstStr[1],
  650.                     menuItemStr[menuItemStr[0] - (j + 4)]);
  651.                 tempInstStr[0] = menuItemStr[0] - (j + 4);
  652.                 
  653.                 // Is it the current instance?
  654.                 HexStrToDecimalNumber ((StringPtr)&tempInstStr, &tempInst);
  655.                 if (tempInst == (long)(gCurrentInstance))
  656.                 {
  657.                     // Check it
  658.                     CheckItem (gInstanceMenu, i, true);
  659.                 }
  660.             }                            
  661.         }
  662.     }
  663.     else    // No instances are currently open, so dim this menu
  664.     {
  665.         DisableItem (gInstanceMenu, 0);
  666.     }
  667.     DrawMenuBar();
  668. }
  669.  
  670. //-----------------------------------------------------------------------
  671.  
  672. void    Enable    (Handle        menu, 
  673.                  short        item, 
  674.                  Boolean    ok)
  675. {
  676.     // Utility routine to enable and disable menu items
  677.     if (ok)
  678.     {
  679.         EnableItem ((MenuHandle) menu, item);
  680.     }
  681.     else
  682.     {
  683.         DisableItem ((MenuHandle) menu, item);
  684.     }
  685. }
  686.  
  687. //-----------------------------------------------------------------------
  688.  
  689. void    HandleMenu    (long    theMenu)
  690. {    
  691.     long                    mSelect;
  692.     short                    menuID;
  693.     short                    menuItem;
  694.     ComponentResult            result = noErr;    
  695.     Str255                    menuItemStr;
  696.     Str255                    tempStr;
  697.     short                    i;
  698.     short                    j;
  699.     ComponentDescription    mathDesc;
  700.     
  701.     // Did we get a menu?
  702.     if (theMenu == 0L)
  703.     {
  704.         // Nope, get it from menu select
  705.         mSelect = MenuSelect (gTheEvent.where);
  706.     }
  707.     else
  708.     {
  709.         // Yep, use it
  710.         mSelect = theMenu;
  711.     }
  712.     
  713.     // Decode it
  714.     menuID = HiWord (mSelect);
  715.     menuItem = LoWord (mSelect);
  716.     
  717.     // Which menu is it?
  718.     switch (menuID)
  719.     {
  720.         case kAppleID:
  721.         {
  722.             if (menuItem == kAboutItem)
  723.             {
  724.                 DoAboutDialog();
  725.             }
  726.             else    // It's a DA
  727.             {
  728.                 Str255    name;
  729.                 
  730.                 // Open the DA
  731.                 GetPort (&gSavedPort);
  732.                 GetItem (gAppleMenu, menuItem, name);
  733.                 OpenDeskAcc (name);
  734.                 SetPort (gSavedPort);
  735.             }
  736.             break;
  737.         }
  738.         case kFileID:
  739.         {
  740.             switch (menuItem)
  741.             {
  742.                 case kOpenItem:
  743.                 {
  744.                     // Open the status dialog
  745.                     OpenStatus();
  746.                     break;
  747.                 }
  748.                 case kCloseItem:
  749.                 {
  750.                     WindowPeek    frontWindow = (WindowPeek) FrontWindow();
  751.                     
  752.                     // Is a window up?
  753.                     if (frontWindow == 0L)
  754.                     {
  755.                         break;
  756.                     }
  757.                     else    // Yep
  758.                     {
  759.                         // What kind of window is it?
  760.                         if (frontWindow->windowKind < 0)
  761.                         {
  762.                             // It's a DA
  763.                             CloseDeskAcc (frontWindow->windowKind);
  764.                         }
  765.                         else
  766.                         {
  767.                             // Is it the status dialog?
  768.                             if (gStatusDialog != nil)
  769.                             {
  770.                                 // Close it
  771.                                 DisposDialog (gStatusDialog);
  772.                                 gStatusDialog = nil;
  773.                             }
  774.                             
  775.                             // Update the menus
  776.                             AdjustMenus();
  777.                         }
  778.                     }
  779.                     break;
  780.                   }
  781.                   
  782.                   #ifdef DEBUG_IT
  783.                     case kOpenMathComponentItem:
  784.                     {
  785.                         OpenMathComponent (kMathComponent);
  786.                         break;
  787.                     }
  788.                 #endif DEBUG_IT
  789.                 
  790.                 case kOpenMoMathComponentItem:
  791.                 {
  792.                     OpenMathComponent (kMoMathComponent);
  793.                     break;
  794.                 }
  795.                 
  796.                 case kOpenNuMathComponentItem:
  797.                 {
  798.                     OpenMathComponent (kNuMathComponent);
  799.                     break;
  800.                 }
  801.                 
  802.                 case kCloseComponentItem:
  803.                 {
  804.                     if (gCurrentInstance != 0L)
  805.                     {
  806.                         // Close the component instance
  807.                         result = CloseComponent (gCurrentInstance);
  808.                         if (result != noErr)
  809.                         {
  810.                             GetIndString (gStatusStr, kStatusStrsID, kErrorClosingInstStr);
  811.                         }
  812.                         else
  813.                         {
  814.                             GetIndString (gStatusStr, kStatusStrsID, kClosedOKStr);
  815.                         }
  816.                         UpdateStatus();
  817.                         
  818.                         // Delete this instance from the instance menu
  819.                         DecimalNumberToHexStr ((long) gCurrentInstance, (StringPtr)&tempStr);
  820.                         for (i = 1; i <= CountMItems (gInstanceMenu); i++)
  821.                         {
  822.                             Str255    tempInstStr;
  823.                             Boolean    foundKey = false;
  824.                             
  825.                             // Extract the instance number from the menu item string
  826.                             GetItem (gInstanceMenu, i, menuItemStr);
  827.                             for (j = 1; j <= menuItemStr[0]; j++)
  828.                             {
  829.                                 if ((gKeyPhrase[1] == menuItemStr[j]) &&
  830.                                     (gKeyPhrase[2] == menuItemStr[j + 1]) &&
  831.                                     (gKeyPhrase[3] == menuItemStr[j + 2]) &&
  832.                                     (gKeyPhrase[4] == menuItemStr[j + 3]) &&
  833.                                     (gKeyPhrase[5] == menuItemStr[j + 4]))
  834.                                 {
  835.                                     foundKey = true;
  836.                                     break;
  837.                                 }
  838.                             }
  839.                             
  840.                             // Did we find the phrase key?
  841.                             if (foundKey)
  842.                             {
  843.                                 // Copy the instance string
  844.                                 BlockMove ((Ptr)&menuItemStr[j + 5], (Ptr)&tempInstStr[1],
  845.                                     menuItemStr[menuItemStr[0] - (j + 4)]);
  846.                                 tempInstStr[0] = menuItemStr[0] - (j + 4);
  847.                                 
  848.                                 // Is this the instance we're closing?
  849.                                 if (RelString (tempInstStr, tempStr, true, true) == 0)
  850.                                 {
  851.                                     // Delete this item from the menu
  852.                                     DelMenuItem (gInstanceMenu, i);
  853.                                     break;
  854.                                 }
  855.                             }                            
  856.                         }
  857.                         
  858.                         // Clear out its slot
  859.                         for (i = 0; i < kMaxInstances; i++)
  860.                         {
  861.                             if (gCurrentInstance == gComponentInstance[i])
  862.                             {
  863.                                 gComponentInstance[i] = 0L;
  864.                                 break;
  865.                             }
  866.                         }
  867.                         gCurrentInstance = 0L;
  868.                         
  869.                         // Set up on another instance in the menu (if there is one)
  870.                         for (i = 0; i < kMaxInstances; i++)
  871.                         {
  872.                             if (gComponentInstance[i] != 0L)
  873.                             {
  874.                                 gCurrentInstance = gComponentInstance[i];
  875.                                 break;
  876.                             }
  877.                         }
  878.                     }
  879.                     
  880.                     // Update the menus
  881.                     AdjustMenus();
  882.                     break;
  883.                 }
  884.                 case kQuitItem:
  885.                 {
  886.                     // We're outta here
  887.                     DoQuit();
  888.                     break;
  889.                 }
  890.                 default:
  891.                 {
  892.                     break;
  893.                 }
  894.             }
  895.             break;
  896.           }    
  897.         case kEditID:
  898.         {
  899.             if (!SystemEdit (menuItem - 1))
  900.             {
  901.                 // We don't really do anything here - feel free to implement something
  902.                 // yourself if you want
  903.                 SysBeep(5);
  904.             }
  905.             break;
  906.         }
  907.         case kTestID:
  908.         {
  909.             Str255    tempStr;
  910.             
  911.             switch (menuItem)
  912.             {
  913.                 case kGetVersionItem:
  914.                 {
  915.                     long    version = GetComponentVersion (gCurrentInstance);
  916.                     
  917.                     tempStr[0] = 0;
  918.                     GetIndString (gStatusStr, kStatusStrsID, kCompVersStr);
  919.                     NumToString ((version >> 16), tempStr);
  920.                     BlockMove ((Ptr)&tempStr[1], (Ptr)&gStatusStr[gStatusStr[0] + 1],
  921.                         tempStr[0]);
  922.                     gStatusStr[0] += tempStr[0];
  923.                     GetIndString (tempStr, kStatusStrsID, kInterfaceVersStr);
  924.                     BlockMove ((Ptr)&tempStr[1], (Ptr)&gStatusStr[gStatusStr[0] + 1],
  925.                         tempStr[0]);
  926.                     gStatusStr[0] += tempStr[0];
  927.                     NumToString ((version & 0x0000FFFF), tempStr);
  928.                     BlockMove ((Ptr)&tempStr[1], (Ptr)&gStatusStr[gStatusStr[0] + 1],
  929.                         tempStr[0]);
  930.                     gStatusStr[0] += tempStr[0] + 1;
  931.                     gStatusStr[gStatusStr[0]] = '.';
  932.                     UpdateStatus();
  933.                     break;
  934.                 }
  935.                 case kGetNameItem:
  936.                 {
  937.                     Handle    nameHdl = NewHandle (sizeof (Str255));
  938.                     
  939.                     if (nameHdl != nil)
  940.                     {
  941.                         result = GetComponentInfo ((Component) gCurrentInstance, 
  942.                             nil, nameHdl, nil, nil);
  943.                         HLock (nameHdl);
  944.                         if ((**nameHdl) == 0)
  945.                         {
  946.                             GetIndString (gStatusStr, kStatusStrsID, kNoNameStr);
  947.                         }
  948.                         else
  949.                         {
  950.                             GetIndString (gStatusStr, kStatusStrsID, kNameStr);
  951.                             BlockMove ((Ptr)&((**((Str255**)(nameHdl)))[1]), 
  952.                                 (Ptr)&gStatusStr[gStatusStr[0] + 1],
  953.                                 (**((Str255**)(nameHdl)))[0]);
  954.                             gStatusStr[0] += (**((Str255**)(nameHdl)))[0] + 2;
  955.                             gStatusStr[gStatusStr[0] - 1] = '”';
  956.                             gStatusStr[gStatusStr[0]] = '.';
  957.                         }
  958.                         HUnlock (nameHdl);
  959.                         DisposHandle (nameHdl);
  960.                     }
  961.                     UpdateStatus();
  962.                     break;
  963.                 }
  964.                 case kGetInfoItem:
  965.                 {
  966.                     Handle    infoHdl = NewHandle (sizeof (Str255));
  967.                     
  968.                     if (infoHdl != nil)
  969.                     {
  970.                         result = GetComponentInfo ((Component) gCurrentInstance, 
  971.                             nil, nil, infoHdl, nil);
  972.                         HLock (infoHdl);
  973.                         if ((**((Str255**)(infoHdl)))[0] == 0)
  974.                         {
  975.                             GetIndString (gStatusStr, kStatusStrsID, kNoInfoStr);
  976.                         }
  977.                         else
  978.                         {
  979.                             GetIndString (gStatusStr, kStatusStrsID, kInfoStr);
  980.                             BlockMove ((Ptr)&((**((Str255**)(infoHdl)))[1]), 
  981.                                 (Ptr)&gStatusStr[gStatusStr[0] + 1],
  982.                                 (**((Str255**)(infoHdl)))[0]);
  983.                             gStatusStr[0] += (**((Str255**)(infoHdl)))[0] + 2;
  984.                             gStatusStr[gStatusStr[0] - 1] = '”';
  985.                             gStatusStr[gStatusStr[0]] = '.';
  986.                         }
  987.                         HUnlock (infoHdl);
  988.                         DisposHandle (infoHdl);
  989.                     }
  990.                     UpdateStatus();
  991.                     break;
  992.                 }
  993.                 case kGetRefconItem:
  994.                 {
  995.                     long    refcon = GetComponentInstanceA5 (gCurrentInstance);
  996.                     
  997.                     NumToString (refcon, tempStr);
  998.                     GetIndString (gStatusStr, kStatusStrsID, kRefconStr);
  999.                     BlockMove ((Ptr)&tempStr[1], (Ptr)&gStatusStr[gStatusStr[0] + 1],
  1000.                         tempStr[0]);
  1001.                     gStatusStr[0] += tempStr[0] + 1;
  1002.                     gStatusStr[gStatusStr[0]] = '.';
  1003.                     UpdateStatus();
  1004.                     break;
  1005.                 }
  1006.                 case kGetCountItem:
  1007.                 {
  1008.                     long    instCount = CountComponentInstances ((Component) gCurrentInstance);
  1009.                     
  1010.                     NumToString (instCount, tempStr);
  1011.                     if (instCount == 1)
  1012.                     {
  1013.                         GetIndString (gStatusStr, kStatusStrsID, kThereIsStr);
  1014.                         BlockMove ((Ptr)&tempStr[1], (Ptr)&gStatusStr[gStatusStr[0] + 1],
  1015.                             tempStr[0]);
  1016.                         gStatusStr[0] += tempStr[0];
  1017.                         GetIndString (tempStr, kStatusStrsID, kInstanceStr);
  1018.                         BlockMove ((Ptr)&tempStr[1], (Ptr)&gStatusStr[gStatusStr[0] + 1],
  1019.                             tempStr[0]);
  1020.                     }
  1021.                     else
  1022.                     {
  1023.                         GetIndString (gStatusStr, kStatusStrsID, kThereAreStr);
  1024.                         BlockMove ((Ptr)&tempStr[1], (Ptr)&gStatusStr[gStatusStr[0] + 1],
  1025.                             tempStr[0]);
  1026.                         gStatusStr[0] += tempStr[0];
  1027.                         GetIndString (tempStr, kStatusStrsID, kInstancesStr);
  1028.                         BlockMove ((Ptr)&tempStr[1], (Ptr)&gStatusStr[gStatusStr[0] + 1],
  1029.                             tempStr[0]);
  1030.                     }
  1031.                     gStatusStr[0] += tempStr[0];
  1032.                     UpdateStatus();
  1033.                     break;
  1034.                 }
  1035.                 case kGetA5Item:
  1036.                 {
  1037.                     long    compA5 = GetComponentInstanceA5 (gCurrentInstance);
  1038.                     
  1039.                     NumToString (compA5, tempStr);
  1040.                     GetIndString (gStatusStr, kStatusStrsID, kA5Str);
  1041.                     BlockMove ((Ptr)&tempStr[1], (Ptr)&gStatusStr[gStatusStr[0] + 1],
  1042.                         tempStr[0]);
  1043.                     gStatusStr[0] += tempStr[0] + 1;
  1044.                     gStatusStr[gStatusStr[0]] = '.';
  1045.                     UpdateStatus();
  1046.                     break;
  1047.                 }
  1048.                 case kDoDivideItem:
  1049.                 {
  1050.                     short    numerator;
  1051.                     short    denominator;
  1052.                     short    quotient;
  1053.                     
  1054.                     DoOperationDialog (&numerator, &denominator);
  1055.                     result = DoDivide (gCurrentInstance, numerator, denominator, 
  1056.                         "ient);
  1057.                     NumToString ((long) quotient, tempStr);
  1058.                     GetIndString (gStatusStr, kStatusStrsID, kDivideResultStr);
  1059.                     BlockMove ((Ptr)&tempStr[1], (Ptr)&gStatusStr[gStatusStr[0] + 1],
  1060.                         tempStr[0]);
  1061.                     gStatusStr[0] += tempStr[0] + 1;
  1062.                     gStatusStr[gStatusStr[0]] = '.';
  1063.                     UpdateStatus();
  1064.                     break;
  1065.                 }
  1066.                 case kDoMultiplyItem:
  1067.                 {
  1068.                     short    firstNum;
  1069.                     short    secondNum;
  1070.                     short    multiplyResult;
  1071.                     
  1072.                     DoOperationDialog (&firstNum, &secondNum);
  1073.                     result = DoMultiply (gCurrentInstance, firstNum, secondNum, 
  1074.                         &multiplyResult);
  1075.                     NumToString ((long) multiplyResult, tempStr);
  1076.                     GetIndString (gStatusStr, kStatusStrsID, kMultiplyResultStr);
  1077.                     BlockMove ((Ptr)&tempStr[1], (Ptr)&gStatusStr[gStatusStr[0] + 1],
  1078.                         tempStr[0]);
  1079.                     gStatusStr[0] += tempStr[0] + 1;
  1080.                     gStatusStr[gStatusStr[0]] = '.';
  1081.                     UpdateStatus();    
  1082.                     break;
  1083.                 }
  1084.                 case kDoAddItem:
  1085.                 {
  1086.                     short    firstNum;
  1087.                     short    secondNum;
  1088.                     short    addResult;
  1089.                     
  1090.                     DoOperationDialog (&firstNum, &secondNum);
  1091.                     result = DoAdd (gCurrentInstance, firstNum, secondNum, &addResult);
  1092.                     NumToString ((long) addResult, tempStr);
  1093.                     GetIndString (gStatusStr, kStatusStrsID, kAddResultStr);
  1094.                     BlockMove ((Ptr)&tempStr[1], (Ptr)&gStatusStr[gStatusStr[0] + 1],
  1095.                         tempStr[0]);
  1096.                     gStatusStr[0] += tempStr[0] + 1;
  1097.                     gStatusStr[gStatusStr[0]] = '.';
  1098.                     UpdateStatus();
  1099.                     break;
  1100.                 }
  1101.                 default:
  1102.                 {
  1103.                     break;
  1104.                 }
  1105.             }
  1106.             break;
  1107.         }
  1108.         case kInstanceID:
  1109.         {
  1110.             Str255    instanceStr;
  1111.             Boolean    foundKey = false;
  1112.             
  1113.             // Get the menu item string
  1114.             GetItem (gInstanceMenu, menuItem, menuItemStr);
  1115.             
  1116.             // Find the key phrase
  1117.             for (i = 1; i <= menuItemStr[0]; i++)
  1118.             {
  1119.                 if ((gKeyPhrase[1] == menuItemStr[i]) &&
  1120.                     (gKeyPhrase[2] == menuItemStr[i + 1]) &&
  1121.                     (gKeyPhrase[3] == menuItemStr[i + 2]) &&
  1122.                     (gKeyPhrase[4] == menuItemStr[i + 3]) &&
  1123.                     (gKeyPhrase[5] == menuItemStr[i + 4]))
  1124.                 {
  1125.                     // Found the key phrase
  1126.                     foundKey = true;
  1127.                     break;
  1128.                 }
  1129.             }
  1130.             
  1131.             // Did we find the key phrase?
  1132.             if (foundKey)
  1133.             {
  1134.                 // Copy the instance string
  1135.                 BlockMove ((Ptr)&menuItemStr[i + 5], (Ptr)&instanceStr[1], 
  1136.                     menuItemStr[0] - (i + 4));
  1137.                 instanceStr[0] = menuItemStr[0] - (i + 4);
  1138.                     
  1139.                 // Get the instance number from the string
  1140.                 HexStrToDecimalNumber ((StringPtr)&instanceStr, (long *)&gCurrentInstance);
  1141.                 
  1142.                 // Update the menus
  1143.                 AdjustMenus();
  1144.                 
  1145.                 // Get the description for this instance
  1146.                 result = GetComponentInfo ((Component) gCurrentInstance, 
  1147.                     &mathDesc, nil, nil, nil);
  1148.                 GetIndString (gStatusStr, kStatusStrsID, kCompDescStr);
  1149.                 BlockMove ((Ptr)&(mathDesc.componentType), 
  1150.                     (Ptr)&(gStatusStr[gStatusStr[0] + 1]), 4);
  1151.                 gStatusStr[0] += 4;
  1152.                 gStatusStr[gStatusStr[0] + 1] = ',';
  1153.                 gStatusStr[gStatusStr[0] + 2] = ' ';
  1154.                 gStatusStr[0] += 2;
  1155.                 BlockMove ((Ptr)&(mathDesc.componentSubType), 
  1156.                     (Ptr)&(gStatusStr[gStatusStr[0] + 1]), 4);
  1157.                 gStatusStr[0] += 4;
  1158.                 gStatusStr[gStatusStr[0] + 1] = ',';
  1159.                 gStatusStr[gStatusStr[0] + 2] = ' ';
  1160.                 gStatusStr[0] += 2;
  1161.                 BlockMove ((Ptr)&(mathDesc.componentManufacturer), 
  1162.                     (Ptr)&(gStatusStr[gStatusStr[0] + 1]), 4);
  1163.                 gStatusStr[0] += 4;
  1164.                 gStatusStr[gStatusStr[0] + 1] = ']';
  1165.                 gStatusStr[gStatusStr[0] + 2] = '.';
  1166.                 gStatusStr[0] += 2;
  1167.                 
  1168.                 // Update the status dialog
  1169.                 UpdateStatus();
  1170.             }            
  1171.             break;
  1172.         }
  1173.         case kCanDoID:
  1174.         {
  1175.             switch (menuItem)
  1176.             {
  1177.                 case kCanDoOpenItem:
  1178.                 {
  1179.                     if (ComponentFunctionImplemented (gCurrentInstance,
  1180.                         kComponentOpenSelect))
  1181.                     {
  1182.                         GetIndString (gStatusStr, kStatusStrsID, kCanDoOpenStr);
  1183.                     }
  1184.                     else
  1185.                     {
  1186.                         GetIndString (gStatusStr, kStatusStrsID, kCantDoOpenStr);
  1187.                     }
  1188.                     UpdateStatus();
  1189.                     break;
  1190.                 }
  1191.                 case kCanDoCloseItem:
  1192.                 {
  1193.                     if (ComponentFunctionImplemented (gCurrentInstance,
  1194.                         kComponentCloseSelect))
  1195.                     {
  1196.                         GetIndString (gStatusStr, kStatusStrsID, kCanDoCloseStr);
  1197.                     }
  1198.                     else
  1199.                     {
  1200.                         GetIndString (gStatusStr, kStatusStrsID, kCantDoCloseStr);
  1201.                     }
  1202.                     UpdateStatus();
  1203.                     break;
  1204.                 }
  1205.                 case kCanDoCanDoItem:
  1206.                 {
  1207.                     if (ComponentFunctionImplemented (gCurrentInstance,
  1208.                         kComponentCanDoSelect))
  1209.                     {
  1210.                         GetIndString (gStatusStr, kStatusStrsID, kCanDoCanDoStr);
  1211.                     }
  1212.                     else
  1213.                     {
  1214.                         GetIndString (gStatusStr, kStatusStrsID, kCantDoCanDoStr);
  1215.                     }
  1216.                     UpdateStatus();
  1217.                     break;
  1218.                 }
  1219.                 case kCanDoVersionItem:
  1220.                 {
  1221.                     if (ComponentFunctionImplemented (gCurrentInstance,
  1222.                         kComponentVersionSelect))
  1223.                     {
  1224.                         GetIndString (gStatusStr, kStatusStrsID, kCanDoVersionStr);
  1225.                     }
  1226.                     else
  1227.                     {
  1228.                         GetIndString (gStatusStr, kStatusStrsID, kCantDoVersionStr);
  1229.                     }
  1230.                     UpdateStatus();
  1231.                     break;
  1232.                 }
  1233.                 case kCanDoRegisterItem:
  1234.                 {
  1235.                     if (ComponentFunctionImplemented (gCurrentInstance,
  1236.                         kComponentRegisterSelect))
  1237.                     {
  1238.                         GetIndString (gStatusStr, kStatusStrsID, kCanDoRegisterStr);
  1239.                     }
  1240.                     else
  1241.                     {
  1242.                         GetIndString (gStatusStr, kStatusStrsID, kCantDoRegisterStr);
  1243.                     }
  1244.                     UpdateStatus();
  1245.                     break;
  1246.                 }
  1247.                 case kCanDoTargetItem:
  1248.                 {
  1249.                     if (ComponentFunctionImplemented (gCurrentInstance,
  1250.                         kComponentTargetSelect))
  1251.                     {
  1252.                         GetIndString (gStatusStr, kStatusStrsID, kCanDoTargetStr);
  1253.                     }
  1254.                     else
  1255.                     {
  1256.                         GetIndString (gStatusStr, kStatusStrsID, kCantDoTargetStr);
  1257.                     }
  1258.                     UpdateStatus();
  1259.                     break;
  1260.                 }
  1261.                 case kCanDoDoDivideItem:
  1262.                 {
  1263.                     if (ComponentFunctionImplemented (gCurrentInstance,
  1264.                         kDoDivideSelect))
  1265.                     {
  1266.                         GetIndString (gStatusStr, kStatusStrsID, kCanDoDoDivideStr);
  1267.                     }
  1268.                     else
  1269.                     {
  1270.                         GetIndString (gStatusStr, kStatusStrsID, kCantDoDoDivideStr);
  1271.                     }
  1272.                     UpdateStatus();
  1273.                     break;
  1274.                 }
  1275.                 case kCanDoDoMultiplyItem:
  1276.                 {
  1277.                     if (ComponentFunctionImplemented (gCurrentInstance,
  1278.                         kDoMultiplySelect))
  1279.                     {
  1280.                         GetIndString (gStatusStr, kStatusStrsID, kCanDoDoMultiplyStr);
  1281.                     }
  1282.                     else
  1283.                     {
  1284.                         GetIndString (gStatusStr, kStatusStrsID, kCantDoDoMultiplyStr);
  1285.                     }
  1286.                     UpdateStatus();
  1287.                     break;
  1288.                 }
  1289.                 case kCanDoDoAddItem:
  1290.                 {
  1291.                     if (ComponentFunctionImplemented (gCurrentInstance, kDoAddSelect))
  1292.                     {
  1293.                         GetIndString (gStatusStr, kStatusStrsID, kCanDoDoAddStr);
  1294.                     }
  1295.                     else
  1296.                     {
  1297.                         GetIndString (gStatusStr, kStatusStrsID, kCantDoDoAddStr);
  1298.                     }
  1299.                     UpdateStatus();
  1300.                     break;
  1301.                 }
  1302.                 default:
  1303.                 {
  1304.                     break;
  1305.                 }
  1306.             }
  1307.             break;
  1308.         }
  1309.         default:
  1310.         {
  1311.             break;
  1312.         }
  1313.     }
  1314. }
  1315.  
  1316. //-----------------------------------------------------------------------
  1317.  
  1318. void    OpenStatus    (void)
  1319. {
  1320.     // Get the dialog
  1321.     gStatusDialog = GetNewDialog (kStatusDialogID, nil, (WindowPtr)-1L);
  1322.     
  1323.     // Did we get it?
  1324.     if (gStatusDialog != nil)
  1325.     {
  1326.         short    itemType;
  1327.         Handle    itemHandle;
  1328.         
  1329.         GetPort (&gSavedPort);
  1330.         SetPort (gStatusDialog);
  1331.         TextFont (geneva);
  1332.         TextFace (0);
  1333.         TextSize (10);
  1334.         GetDItem (gStatusDialog, kStatusBox, &itemType, &gStatusText, &gStatusBox);
  1335.         InsetRect (&gStatusBox, -2, -2);
  1336.         FrameRect (&gStatusBox);
  1337.         InsetRect (&gStatusBox, 2, 2);
  1338.         EraseRect (&gStatusBox);
  1339.         SetIText (gStatusText, gStatusStr);
  1340.     }
  1341.     
  1342.     // Update the menus
  1343.     AdjustMenus();
  1344. }
  1345.  
  1346. //-----------------------------------------------------------------------
  1347.  
  1348. void    UpdateStatus    (void)
  1349. {
  1350.     // If we've got a status dialog, update it
  1351.     if (gStatusDialog != nil)
  1352.     {
  1353.         GetPort (&gSavedPort);
  1354.         SetPort (gStatusDialog);
  1355.         InvalRect (&gStatusBox);
  1356.         SetPort (gSavedPort);
  1357.     }
  1358. }
  1359.  
  1360. //-----------------------------------------------------------------------
  1361.  
  1362. void    OpenMathComponent    (MathType    whichOne)
  1363. {
  1364.     short        i;
  1365.     Str255        tempStr;
  1366.     Component    mathComponentID;
  1367.     short        mathTypeStrID;
  1368.     Boolean        foundSlot = false;
  1369.     
  1370.     // Which type of component do we want to open?
  1371.     switch (whichOne)
  1372.     {
  1373.         case kMathComponent:
  1374.             mathComponentID = gMathComponentID;
  1375.             mathTypeStrID = kMathStr;
  1376.             break;
  1377.         case kMoMathComponent:
  1378.             mathComponentID = gMoMathComponentID;
  1379.             mathTypeStrID = kMoMathStr;
  1380.             break;
  1381.         case kNuMathComponent:
  1382.             mathComponentID = gNuMathComponentID;
  1383.             mathTypeStrID = kNuMathStr;
  1384.             break;
  1385.         default:
  1386.             break;
  1387.     }
  1388.     
  1389.     // Were we asked to open some type of Math component?
  1390.     if (mathComponentID != 0L)
  1391.     {
  1392.         // Find an open slot
  1393.         for (i = 0; i < kMaxInstances; i++)
  1394.         {
  1395.             // Is this slot open?
  1396.             if (gComponentInstance[i] == 0L)
  1397.             {
  1398.                 // Open the component
  1399.                 gComponentInstance[i] = 
  1400.                     (MathComponent) OpenComponent (mathComponentID);
  1401.                 gCurrentInstance = gComponentInstance[i];
  1402.                 foundSlot = true;
  1403.                 break;
  1404.             }
  1405.         }
  1406.     }
  1407.     else    // We were not asked to find some kind of Math component
  1408.     {
  1409.         GetIndString (gStatusStr, kStatusStrsID, kDidNotFindCompIDStr);
  1410.     }
  1411.     
  1412.     // There were no open slots (we've opened as many instances as our test
  1413.     // program will allow)
  1414.     if (!foundSlot)
  1415.     {
  1416.         GetIndString (gStatusStr, kStatusStrsID, kCantOpenAnyMoreInstStr);
  1417.     }
  1418.     else if (gCurrentInstance != 0L)    // We successfully opened the component
  1419.     {
  1420.         Str255    mathTypeStr;
  1421.         
  1422.         GetIndString (mathTypeStr, kStatusStrsID, mathTypeStrID);
  1423.         GetIndString (gStatusStr, kStatusStrsID, kFoundCompIDAndInstStr);
  1424.         DecimalNumberToHexStr ((long) gCurrentInstance, (StringPtr)&tempStr);
  1425.         BlockMove ((Ptr)&tempStr[1], (Ptr)&mathTypeStr[mathTypeStr[0] + 1],
  1426.             tempStr[0]);
  1427.         mathTypeStr[0] += tempStr[0];
  1428.         InsMenuItem (gInstanceMenu, mathTypeStr, 255);
  1429.     }
  1430.     else    // We couldn't open an instance of the component
  1431.     {
  1432.         GetIndString (gStatusStr, kStatusStrsID, kDidNotGetInstStr);
  1433.     }
  1434.     
  1435.     // Update everything
  1436.     UpdateStatus();
  1437.     AdjustMenus();
  1438. }
  1439.  
  1440. //-----------------------------------------------------------------------
  1441.  
  1442. void    DoAboutDialog    (void)
  1443. {
  1444.     short        itemHit;
  1445.     short        itemType;
  1446.     Handle        itemHandle;
  1447.     Rect        itemRect;
  1448.     DialogPtr    aboutDialog = GetNewDialog (kAboutDialogID, nil, (WindowPtr)-1L);
  1449.  
  1450.     // Do the boring about dialog
  1451.     GetDItem (aboutDialog, kOKButtonOutline, &itemType, &itemHandle, &itemRect);
  1452.     SetDItem (aboutDialog, kOKButtonOutline, itemType, 
  1453.         (Handle) DrawOKOutline, &itemRect);
  1454.     do
  1455.     {
  1456.         ModalDialog (nil, &itemHit);
  1457.     }
  1458.     while (itemHit != kOKButton);
  1459.     DisposDialog (aboutDialog);
  1460. }
  1461.  
  1462. //-----------------------------------------------------------------------
  1463.  
  1464. void    DoOperationDialog    (short    *firstNum,
  1465.                              short    *secondNum)
  1466. {
  1467.     DialogPtr    opDialog = GetNewDialog (kOpDialogID, nil, (WindowPtr)-1L);
  1468.     
  1469.     // Did we get a dialog?
  1470.     if (opDialog != nil)
  1471.     {
  1472.         short    itemHit;
  1473.         short    itemType;
  1474.         Handle    itemHandle;
  1475.         Rect    itemRect;
  1476.         Str255    tempStr;
  1477.         long    tempNum;
  1478.         
  1479.         GetDItem (opDialog, kFirstNumBox, &itemType, &itemHandle, &itemRect);
  1480.         NumToString (23L, tempStr);
  1481.         SetIText (itemHandle, tempStr);
  1482.         
  1483.         GetDItem (opDialog, kSecondNumBox, &itemType, &itemHandle, &itemRect);
  1484.         NumToString (4L, tempStr);
  1485.         SetIText (itemHandle, tempStr);
  1486.         
  1487.         // Go get two numbers from the user
  1488.         do
  1489.         {
  1490.             ModalDialog (nil, &itemHit);
  1491.         }
  1492.         while (itemHit != kOKButton);
  1493.         
  1494.         // Give the two numbers back to the caller
  1495.         GetDItem (opDialog, kFirstNumBox, &itemType, &itemHandle, &itemRect);
  1496.         GetIText (itemHandle, tempStr);
  1497.         StringToNum (tempStr, &tempNum);
  1498.         *firstNum = (short) tempNum;
  1499.         
  1500.         GetDItem (opDialog, kSecondNumBox, &itemType, &itemHandle, &itemRect);
  1501.         GetIText (itemHandle, tempStr);
  1502.         StringToNum (tempStr, &tempNum);
  1503.         *secondNum = (short) tempNum;
  1504.         
  1505.         // Clean up
  1506.         DisposDialog (opDialog);
  1507.     }
  1508. }
  1509.  
  1510. //-----------------------------------------------------------------------
  1511.  
  1512. static    pascal    void    DrawOKOutline    (DialogPtr    theDialog,
  1513.                                          short        theItem)
  1514. {
  1515.     short    itemType;
  1516.     Handle    itemHandle;
  1517.     Rect    itemRect;
  1518.     
  1519.     // Draws the OK button outline
  1520.     SetPort (theDialog);
  1521.     GetDItem (theDialog, kOKButtonOutline, &itemType, &itemHandle, &itemRect);
  1522.     PenSize (3, 3); 
  1523.     InsetRect (&itemRect, -4, -4);
  1524.     FrameRoundRect (&itemRect, 16, 16);
  1525.     PenSize (1, 1);
  1526. }
  1527.  
  1528. //-----------------------------------------------------------------------
  1529.  
  1530. void    DoQuit    (void)
  1531. {
  1532.     ComponentResult    result = noErr;
  1533.     short            i;
  1534.     
  1535.     // Walk our instance array and close all instances
  1536.     for (i = 0; i < kMaxInstances; i++)
  1537.     {
  1538.         if (gComponentInstance[i] != 0L)
  1539.         {
  1540.             result = CloseComponent (gComponentInstance[i]);
  1541.             gComponentInstance[i] = 0L;
  1542.         }
  1543.     }
  1544.     // Note that it's not necessary to unregister the components
  1545.     // or dispose of the string handles for the name and info
  1546.     // strings when we're in debug mode - this is because we registered 
  1547.     // the components locally, and as soon as the application heap 
  1548.     // shuts down (that is, the app quits), the Component Manager 
  1549.     // automatically unregisters any components local to that app heap and 
  1550.     // disposes of the component handles properly.
  1551.     
  1552.     // Set quit flag
  1553.     gQuitFlag = true;
  1554. }
  1555.  
  1556. //-----------------------------------------------------------------------
  1557.  
  1558. void    DecimalNumberToHexStr    (long        theDecimalNumber,
  1559.                                  StringPtr    theHexStr)
  1560. {
  1561.     // Utility routine to convert a decimal number into a
  1562.     // hex number string    
  1563.     
  1564.     long    testNybble;
  1565.     char    hexStr[8];
  1566.     Str255    tempStr;
  1567.     short    i;
  1568.     short    j;
  1569.     
  1570.     for (i = 7; i >= 0; i--)
  1571.     {
  1572.         testNybble = (theDecimalNumber & (0xF0000000 >> (4 * i))) >> ((7 - i) * 4);
  1573.         
  1574.         if ((testNybble == 8) || (testNybble == 9))    // is it 8 or 9?
  1575.         {
  1576.             NumToString (testNybble, tempStr);
  1577.             hexStr[i] = tempStr[1];
  1578.         }
  1579.         else if ((testNybble & 0x00000008) == 1)    // is it between A and F?
  1580.         {
  1581.             if (testNybble == 10)
  1582.                 hexStr[i] = 'A';
  1583.             else if (testNybble == 11)
  1584.                 hexStr[i] = 'B';
  1585.             else if (testNybble == 12)
  1586.                 hexStr[i] = 'C';
  1587.             else if (testNybble == 13)
  1588.                 hexStr[i] = 'D';
  1589.             else if (testNybble == 14)
  1590.                 hexStr[i] = 'E';
  1591.             else if (testNybble == 15)
  1592.                 hexStr[i] = 'F';
  1593.         }
  1594.         else                                        // it's between 0 and 7
  1595.         {
  1596.             NumToString (testNybble, tempStr);
  1597.             hexStr[i] = tempStr[1];
  1598.         }
  1599.     }
  1600.     BlockMove ((Ptr)&hexStr, (Ptr)&theHexStr[1], 8);
  1601.     theHexStr[0] = 8;
  1602. }
  1603.  
  1604. //-----------------------------------------------------------------------
  1605.  
  1606. OSErr    HexStrToDecimalNumber    (StringPtr    theHexStr,
  1607.                                  long        *theDecimalNumber)
  1608. {
  1609.     // Utility routine to convert a hex number string into
  1610.     // a decimal number
  1611.     
  1612.     OSErr    result = noErr;
  1613.     long    decimalNum = 0L;
  1614.     short    i;
  1615.     long    hexDigitValue;
  1616.     Str255    tempStr;
  1617.     
  1618.     tempStr[0] = 1;
  1619.     if (theHexStr[0] > 8)
  1620.     {
  1621.         result = kGenericError;
  1622.     }
  1623.     else
  1624.     {
  1625.         for (i = 1; i <= 8; i++)
  1626.         {
  1627.             if (theHexStr[i] >= 0x30 && theHexStr[i] <= 0x39)    // it's between 0 and 9
  1628.             {
  1629.                 tempStr[1] = theHexStr[i];
  1630.                 StringToNum (tempStr, &hexDigitValue);
  1631.                 decimalNum += hexDigitValue << (4 * (8 - i));
  1632.             }
  1633.             else if ((theHexStr[i] >= 0x41 && theHexStr[i] <= 0x46) ||
  1634.                 (theHexStr[i] >= 0x61 && theHexStr[i] <= 0x66))    // it's between A and F
  1635.             {
  1636.                 switch (theHexStr[i])
  1637.                 {
  1638.                     case 'A':
  1639.                     case 'a':
  1640.                         hexDigitValue = 10;
  1641.                         break;
  1642.                     case 'B':
  1643.                     case 'b':
  1644.                         hexDigitValue = 11;
  1645.                         break;
  1646.                     case 'C':
  1647.                     case 'c':
  1648.                         hexDigitValue = 12;
  1649.                         break;
  1650.                     case 'D':
  1651.                     case 'd':
  1652.                         hexDigitValue = 13;
  1653.                         break;
  1654.                     case 'E':
  1655.                     case 'e':
  1656.                         hexDigitValue = 14;
  1657.                         break;
  1658.                     case 'F':
  1659.                     case 'f':
  1660.                         hexDigitValue = 15;
  1661.                         break;
  1662.                 }
  1663.                 decimalNum += hexDigitValue << (4 * (8 - i));
  1664.             }
  1665.             else
  1666.             {
  1667.                 result = kGenericError;
  1668.             }
  1669.         }
  1670.     }
  1671.     
  1672.     *theDecimalNumber = decimalNum;    
  1673.     return (result);
  1674. }
  1675.                              
  1676. //-----------------------------------------------------------------------
  1677.  
  1678.